package com.gaoding.shared.dict.provider;

import com.gaoding.commons.exception.NotFoundException;
import com.gaoding.commons.exception.ServiceException;
import com.gaoding.commons.exception.ValidateException;
import com.gaoding.grpc.common.protobuf.Common;
import com.gaoding.orm.jpa.search.BaseSearchable;
import com.gaoding.orm.jpa.search.SearchOperator;
import com.gaoding.shared.dict.common.constant.DictMessageConstant;
import com.gaoding.shared.dict.entity.DictLanguage;
import com.gaoding.shared.dict.entity.DictTextContent;
import com.gaoding.shared.dict.enums.DictServiceErrorCode;
import com.gaoding.shared.dict.repository.DictLanguageRepository;
import com.gaoding.shared.dict.repository.DictTextContentRepository;
import com.gaoding.shared.dict.rpc.service.*;
import com.gaoding.shared.dict.service.DictLanguageService;
import com.gaoding.shared.dict.service.DictTextContentService;
import com.google.protobuf.BoolValue;
import com.google.protobuf.Int64Value;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.server.service.GrpcService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.data.domain.Page;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 多语言信息服务 grpc实现
 *
 * @author mobai
 * @since 2021/1/27 15:43
 */
@GrpcService
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class DictLanguageServiceGrpcImpl extends GdGrpcDictLanguageService {

    /**
     * 多语言信息服务组件
     */
    private final DictLanguageService dictLanguageService;

    /**
     * 字典内容配置服务组件
     */
    private final DictTextContentService dictTextContentService;


    private final DictTextContentRepository dictTextContentRepository;

    /**
     * 分页查询多语言信息累表
     *
     * @param request 查询参数
     * @return com.gaoding.shared.dict.rpc.service.DictLanguageReply
     * @since 2021/2/1 9:29 上午
     */
    @Override
    public DictLanguageReply list(QueryDictLanguageRequest request) {
        DictLanguageReply reply = DictLanguageReply.newBuilder().addAllData(Collections.emptyList()).build();
        BaseSearchable searchable = BaseSearchable.newSearchable();
        if (StringUtils.isNotBlank(request.getLanguageCode())) {
            searchable.addSearchFilter("languageCode", SearchOperator.eq, request.getLanguageCode());
        }
        if (request.hasId()) {
            searchable.addSearchFilter("id", SearchOperator.eq, request.getId().getValue());
        }
        Common.Page queryPage = request.getPage();
        searchable.setPage(queryPage.getPageNum(), queryPage.getPageSize());
        Page<DictLanguage> languagePage = dictLanguageService.findAll(searchable);
        if (!CollectionUtils.isEmpty(languagePage.getContent())) {
            List<DictLanguageInfo> languageInfos = languagePage.getContent().stream().map(this::transfer).collect(Collectors.toList());
            reply = DictLanguageReply.newBuilder().addAllData(languageInfos).build();
        }
        return reply;
    }

    /**
     * 新增多语言记录
     *
     * @param request 新增参数
     * @return com.google.protobuf.BoolValue 成功 true 失败 false
     * @since 2021/2/1 9:30 上午
     */

    @Override
    public Int64Value create(CreateDictLanguageRequest request) {
        if (StringUtils.isBlank(request.getLanguageCode())) {
            throw new ValidateException("语言编码不得为空");
        }
        DictLanguageRepository repository = (DictLanguageRepository) dictLanguageService.getRepository();
        List<DictLanguage> languages = repository.findAllByLanguageCode(request.getLanguageCode());
        if (CollectionUtils.isNotEmpty(languages)) {
            throw new ServiceException(DictServiceErrorCode.LANGUAGE_CODE_EXIST);
        }
        DictLanguage saveEntity = DictLanguage.builder().status(DictMessageConstant.DEFAULT_STATUS).languageCode(request.getLanguageCode()).languageName(request.getLanguageName()).build();
        try {

            return Int64Value.of(dictLanguageService.save(saveEntity).getId());
        } catch (Exception e) {
            log.error("新增多语言记录出错，原因:{}", e.getMessage());
            throw e;
        }
    }

    /**
     * 更新多语言信息
     *
     * @param request 更新参数
     * @return com.google.protobuf.BoolValue 成功 true 失败 false
     * @since 2021/2/1 9:34 上午
     */

    @Override
    public BoolValue update(UpdateDictLanguageRequest request) {
        //判断修改完后的code不为空且不存在表中
        if (StringUtils.isBlank(request.getLanguageCode())) {
            throw new ValidateException("语言编码不得为空");
        }
        long num = dictLanguageService.count(BaseSearchable.newSearchable().addSearchFilter("languageCode", SearchOperator.eq, request.getLanguageCode()).addSearchFilter("id",SearchOperator.ne,request.getId()));
        if (num > 0) {
            throw new ServiceException(DictServiceErrorCode.LANGUAGE_CODE_EXIST);
        }
        DictLanguage language = dictLanguageService.findOne(request.getId());
        if (language == null) {
            throw new ServiceException(DictServiceErrorCode.LANGUAGE_NOT_EXIST);
        }
        if (!language.getLanguageCode().equals(request.getLanguageCode())) {
            List<DictTextContent> textContents = dictTextContentRepository.findAllByLanguageCode(request.getLanguageCode());
            if (CollectionUtils.isNotEmpty(textContents)) {
                throw new ServiceException(DictServiceErrorCode.LANGUAGE_IS_CONFIGURED);
            }
        }
        language.setLanguageCode(request.getLanguageCode()).setLanguageName(request.getLanguageName());
        try {
           dictLanguageService.save(language);
            return BoolValue.of(true);
        } catch (Exception e) {
            log.error("更新多语言信息出错,原因:{}", e.getMessage());
            return BoolValue.of(false);
        }

    }

    /**
     * 根据id删除多语言信息记录（逻辑删除）
     *
     * @param request id
     * @return com.google.protobuf.BoolValue 成功 true 失败 false
     * @since 2021/2/1 9:34 上午
     */

    @Override
    public BoolValue delete(Int64Value request) {
        try {
            dictLanguageService.delete(request.getValue());
            return BoolValue.of(true);
        } catch (EmptyResultDataAccessException ignored) {
            log.error("id为{}的多语言信息记录已不存在", request.getValue());
            throw new NotFoundException(String.format("id为%s的多语言信息记录已不存在", request.getValue()));
        }

    }

    /**
     * 实体转dto
     *
     * @param d 实体
     * @return com.gaoding.shared.dict.rpc.service.DictLanguageInfo 分页查询的封装实体
     * @since 2021/2/1 9:36 上午
     */

    private DictLanguageInfo transfer(DictLanguage d) {
        if (d == null) {
            return null;
        }
        return DictLanguageInfo.newBuilder().setId(d.getId()).setLanguageCode(d.getLanguageCode())
                .setLanguageName(d.getLanguageName()).build();
    }
}
